﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Hvac;

namespace SimpleConsoleSample
{
    class SimpleConsoleSystem : IHvacSystem
    {
        IHvacController _hc;
        ICollection<Zone> _therms;

        public SimpleConsoleSystem()
        {
            _hc = new SimpleHvacController();

            _therms = new List<Zone>();

            Zone t = new Zone("Master", new Damper("Master"), new SimpleTemperatureSensor("Master", 21, 26), 22, 25, SatisfyOption.MustSatisfy);
            _therms.Add(t);

            t = new Zone("Den", new Damper("Den"), new SimpleTemperatureSensor("Den", 23, 28), 22, 25, SatisfyOption.MustSatisfy);
            _therms.Add(t);
        }

        #region IHvacSystem Members

        public IHvacController HvacController
        {
            get { return _hc; }
        }

        public IEnumerable<Zone> Zones
        {
            get { return _therms; }
        }

        #endregion

        #region SimpleHvacController Example

        class SimpleHvacController : IHvacController
        {
            private bool _isRunning;
            private int _mode;
            private bool _isEnabled;
            private FanMode _fanStatus;

            public SimpleHvacController()
            {
                _fanStatus = FanMode.Auto;
            }

            protected virtual void OnHvacChanged(HvacChangedEventArgs e)
            {
                Console.WriteLine("Hvac Status: Mode: {0}, IsRunning {1}", _mode, _isRunning);
                if (HvacChanged != null)
                    HvacChanged(this, e);
            }

            #region IHvacController Members

            public event EventHandler<HvacChangedEventArgs> HvacChanged;

            public bool IsRunning
            {
                get { return _isRunning; }
            }

            public void Demand(double factor)
            {
                if (factor == 0)
                {
                    _isRunning = false;
                    OnHvacChanged(new HvacChangedEventArgs(_isRunning, _mode));
                }
                else
                {
                    _isRunning = true;
                    OnHvacChanged(new HvacChangedEventArgs(_isRunning, _mode));
                }
            }

            public int Mode
            {
                get
                {
                    return _mode;
                }
                set
                {
                    _mode = value;
                    OnHvacChanged(new HvacChangedEventArgs(_isRunning, _mode));
                }
            }

            public FanMode FanStatus
            {
                get
                {
                    return _fanStatus;
                }
                set
                {
                    _fanStatus = value;
                }
            }

            public bool Enabled
            {
                get
                {
                    return _isEnabled;
                }
                set
                {
                    _isEnabled = value;
                    if (!_isEnabled)
                    {
                        _mode = 0;
                        OnHvacChanged(new HvacChangedEventArgs(_isRunning, _mode));
                    }
                }
            }

            #endregion
        }
        #endregion

        #region SimpleTemperatureSensor Example

        class SimpleTemperatureSensor : ITemperatureSensor
        {
            double _temperature;
            double _high;
            double _low;
            bool _isRising;
            string _name;

            public SimpleTemperatureSensor()
            {
            }

            public SimpleTemperatureSensor(string name, double low, double high)
            {
                _name = name;
                _low = low;
                _high = high;
                _temperature = (int)(_low + (_high - _low) / 2);
                _isRising = true;
                Timer t = new Timer(new TimerCallback(tcb), this, 5 * 1000, 5 * 1000);
            }

            void tcb(object state)
            {
                double lastTemperature = _temperature;

                if (_isRising)
                    _temperature++;
                else
                    _temperature--;

                if (_temperature > _high)
                {
                    _isRising = false;
                    _temperature--;
                }
                else if (_temperature < _low)
                {
                    _isRising = true;
                    _temperature++;
                }

                if (_temperature != lastTemperature)
                    OnTemperatureChanged(lastTemperature, _temperature);
            }

            public virtual void OnTemperatureChanged(double oldTemperature, double newTemperature)
            {
                Console.WriteLine("Temperature: {0} {1}", _name, _temperature);
                if (TemperatureChanged != null)
                    TemperatureChanged(this, new TemperatureChangedEventArgs(oldTemperature, newTemperature));
            }

            #region ITemperatureSensor Members

            public double Temperature
            {
                get { return _temperature; }
            }

            public event EventHandler<TemperatureChangedEventArgs> TemperatureChanged;

            #endregion
        }

        #endregion

        #region IAirVolumeController example

        class Damper : IAirVolumeController
        {
            double _lastPosition;
            string _name;

            public Damper(string name)
            {
                _name = name;
                SetVolume(1);
            }

            #region IDamper Members

            public void SetVolume(double position)
            {
                if (position != _lastPosition)
                {
                    _lastPosition = position;
                    Console.WriteLine("Damper Position: {0} {1:P0}", _name, position);
                }
            }

            #endregion
        }

        #endregion
    }
}
